package botlab.control;

import botlab.Entity;
import botlab.Game;
import botlab.gui.Notifier;
import com.jme3.input.ChaseCamera;
import com.jme3.input.FlyByCamera;
import com.jme3.input.KeyInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.math.FastMath;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.renderer.Camera;
import com.jme3.scene.Spatial;
import com.jme3.scene.control.Control;

/**
 *
 * @author Quentin
 */
public class CameraControl extends BaseControl implements ActionListener
{

    private Camera cam;
    private FlyByCamera flyCam;
    private ChaseCamera chaseCam;
    private int index;

    public CameraControl(Camera cam, Entity target)
    {
        index = 0;
        target.addControl(this);
        this.cam = cam;
        this.flyCam = Game.getApp().getFlyByCamera();
        this.flyCam.setDragToRotate(true);
        cam.setRotation(Quaternion.DIRECTION_Z);
        this.chaseCam = new ChaseCamera(cam, target.getSpatial(),
                Game.getApp().getInputManager());
        this.chaseCam.setDefaultHorizontalRotation(-FastMath.DEG_TO_RAD * 90);
        this.chaseCam.setDefaultVerticalRotation(0);

        setCamera(index);

        Quaternion rot = target.getSpatial().getWorldRotation();
        cam.setLocation(target.getSpatial().getWorldTranslation().add(rot.mult(new Vector3f(
                0, 5f, -15f))));
        cam.lookAt(target.getSpatial().getWorldTranslation(), Vector3f.UNIT_Y);

        customFlyByCameraMapping();
        registerInput();
    }

    private void customFlyByCameraMapping()
    {
        String[] mappings = new String[]
        {
            "FLYCAM_Left",
            "FLYCAM_Right",
            "FLYCAM_Up",
            "FLYCAM_Down",
            "FLYCAM_StrafeLeft",
            "FLYCAM_StrafeRight",
            "FLYCAM_Forward",
            "FLYCAM_Backward",
            "FLYCAM_ZoomIn",
            "FLYCAM_ZoomOut",
            "FLYCAM_RotateDrag",
            "FLYCAM_Rise",
            "FLYCAM_Lower"
        };

        // Remove last mapping for the flyByCam
        inputManager.removeListener(flyCam);

        // Change the mappings we don’t want
        inputManager.deleteMapping("FLYCAM_StrafeLeft");
        inputManager.addMapping("FLYCAM_StrafeLeft", new KeyTrigger(
                KeyInput.KEY_Q));
        inputManager.deleteMapping("FLYCAM_StrafeRight");
        inputManager.addMapping("FLYCAM_StrafeRight", new KeyTrigger(
                KeyInput.KEY_D));
        inputManager.deleteMapping("FLYCAM_Forward");
        inputManager.addMapping("FLYCAM_Forward", new KeyTrigger(KeyInput.KEY_Z));
        inputManager.deleteMapping("FLYCAM_Backward");
        inputManager.addMapping("FLYCAM_Backward",
                new KeyTrigger(KeyInput.KEY_S));
        inputManager.deleteMapping("FLYCAM_Rise");
        inputManager.addMapping("FLYCAM_Rise", new KeyTrigger(KeyInput.KEY_A));
        inputManager.deleteMapping("FLYCAM_Lower");
        inputManager.addMapping("FLYCAM_Lower", new KeyTrigger(KeyInput.KEY_W));

        // Recreate the mapping for the flyByCam
        inputManager.addListener(flyCam, mappings);
    }

    public void cleanup()
    {
        inputManager.removeListener(this);
        inputManager.removeListener(chaseCam);
    }

    @Override
    protected void controlUpdate(float tpf)
    {
        Quaternion rot = spatial.getWorldRotation();
        cam.setLocation(spatial.getWorldTranslation().add(rot.mult(new Vector3f(
                0, 5f, -15f))));
        cam.lookAt(spatial.getWorldTranslation(), Vector3f.UNIT_Y);
    }

    private void registerInput()
    {
        String[] input =
        {
            "switch_view"
        };
        inputManager.addMapping("switch_view", new KeyTrigger(KeyInput.KEY_TAB));
        inputManager.addListener(this, input);

    }

    public void onAction(String name, boolean pressed, float tpf)
    {
        if (name.equals("switch_view") && !pressed)
        {
            index = (index + 1) % 3;
            setCamera(index);
        }
    }

    public void setCamera(int i)
    {
        switch (i)
        {
            case 0:
                java.awt.EventQueue.invokeLater(new Runnable()
                {
                    public void run()
                    {
                        Notifier.getInstance().enterState("render");
                    }
                });
                flyCam.setEnabled(false);
                chaseCam.setEnabled(false);
                this.setEnabled(true);
                break;
            case 1:
                java.awt.EventQueue.invokeLater(new Runnable()
                {
                    public void run()
                    {
                        Notifier.getInstance().enterState("render2");
                    }
                });
                this.setEnabled(false);
                chaseCam.setEnabled(false);
                flyCam.setEnabled(true);
                break;
            case 2:
                java.awt.EventQueue.invokeLater(new Runnable()
                {
                    public void run()
                    {
                        Notifier.getInstance().enterState("render3");
                    }
                });
                this.setEnabled(false);
                flyCam.setEnabled(false);
                chaseCam.setEnabled(true);
                break;
            default:
                break;

        }
    }

    @Override
    public Control cloneForSpatial(Spatial spatial)
    {
        throw new UnsupportedOperationException("Not supported yet.");
    }
}
